#pragma once

#include <time.h>
#include "LinkedList.h"
#include "Buffer.h"

class CClient;

// 协议类型
enum class ProtType : uint8_t
{
    Invalide,
    Custom,
    WebSocket
};

struct ClientPtr
{
    CClient *pClnt;

    ClientPtr() { pClnt = nullptr; }
    virtual ~ClientPtr() { DestroyClient(); };

    bool NewClient(int ifd);
    void DestroyClient();
};

typedef CLinkedListEx<ClientPtr> CClientList;
typedef CClientList::Node ClientNode;

class CClient
{
public:
    CClient(int ifd);
    ~CClient();

    void *operator new(size_t sz);
    void operator delete(void *ptr);

    bool Init();
    void Destroy();

    // 接收数据到m_bufRecv
    int Recv() { return m_bufRecv.Recv(); }
    // 读取m_bufRecv中的数据
    int Read(void *pDest, int iLen) { return m_bufRecv.Read(pDest, iLen); }

    // socket可写时发送m_bufSend中已有数据
    int Send() { return m_bufSend.Send(); }

    // m_bufSend中无数据时发送外部数据，没发送完则缓冲到m_bufSend
    int Send(void *pSrc, int iLen) { return m_bufSend.Send(pSrc, iLen); }

    void SetBelongNode(ClientNode *pNode) { m_pClntNode = pNode; }
    int GetSocketDescriptor() { return m_ifd; }

    bool HasNeedSendData() { return m_bufSend.GetDataLength() > 0; }

private:
    const int m_ifd;  // socket描述符
    bool m_bFirst;    // 是否第一包
    bool m_bSsl;      // 是否SSL
    ProtType m_eProt; // 协议类型
    uint8_t m_nMod;   // 归属模块
    time_t m_tLast;   // 最后一次输入时间

    CBuffer<> m_bufRecv;          // 接收缓冲
    CBuffer<CSpinLock> m_bufSend; // 发送缓冲

    ClientNode *m_pClntNode; // 本client在Server中的m_lstClnt的Node指针
};